#ifndef __THREADPOOL_H_
#define __THREADPOOL_H_

#include "BlockingQueue.h"
#include "Task.h"

#include <thread>
#include <vector>

namespace Util
{
	class ThreadPool
	{
	public:
		ThreadPool(int max_thread_num = 5)
			:_run_flg(false), _max_thread_num(max_thread_num)
		{
		}

		~ThreadPool()
		{
			// Stop all Thread
			stop_task();
		}

		void start_task()
		{
			if (_run_flg)
				return;

			_run_flg = true;

			// start all worker threads
			for (int i = 0; i < _max_thread_num; i++)
			{
				_thread_list.push_back(std::thread(ThreadPool::worker_thread, this));
			}
		}

		void stop_task()
		{
			// Stop all Thread
			_run_flg = false;

			// Wait for all threads quit
			for (auto& t : _thread_list) {
				t.join();
			}
			_thread_list.clear();

			// clear undo task
			Task* task;
			while (_task_list.try_take(task))
			{
				if (task->is_auto_delete())
					delete task;
			}
		}

		bool is_running()
		{
			return _run_flg;
		}

		void push_task(Task *task)
		{
			// push task to queue
			_task_list.put(task);
		}

		bool pop_task(Task* &task)
		{
			// test task from queue without block
			return _task_list.take_for(task, 3);
		}

	private:
		static void worker_thread(ThreadPool* pool)
		{
			Task* task;
			while (pool->is_running())
			{
				if (pool->pop_task(task))
				{
					task->run();
					if (task->is_auto_delete())
						delete task;
					task = NULL;
				}
			}
		}

	private:
		BlockingQueue<Task*> _task_list;
		std::vector<std::thread> _thread_list;
		bool _run_flg;
		int _max_thread_num;
	};
}

#endif //__THREADPOOL_H_